package com.gitee.cliveyuan.tools.codec;

import com.gitee.cliveyuan.tools.Assert;
import com.gitee.cliveyuan.tools.StringTools;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Objects;

/**
 * AES加密工具
 *
 * @author clive
 * Created on 2018-07-24
 */
public class AESTools {

    private static final String AES_TYPE = "AES/ECB/PKCS5Padding";
    private static final String ALGORITHM = "AES";
    private static final Logger logger = LoggerFactory.getLogger(AESTools.class);

    private AESTools() {
    }


    /**
     * 加密
     *
     * @param aesKey 密钥
     * @param data   明文数据
     */
    public static String encrypt(String aesKey, String data) {
        validate(aesKey);
        if (StringTools.isBlank(data)) return null;
        byte[] encrypt = null;
        try {
            Key key = generateKey(aesKey);
            Cipher cipher = Cipher.getInstance(AES_TYPE);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            encrypt = cipher.doFinal(data.getBytes());
        } catch (Exception e) {
            logger.error("encrypt Exception", e);
            e.printStackTrace();
        }
        byte[] bytes = Base64.encodeBase64(encrypt);
        if (Objects.isNull(bytes)) return null;
        return new String(bytes);
    }

    /**
     * 解密
     *
     * @param aesKey      密钥
     * @param encryptData 密文数据
     */
    public static String decrypt(String aesKey, String encryptData) {
        validate(aesKey);
        if (StringTools.isBlank(encryptData)) return null;
        byte[] decrypt;
        try {
            Key key = generateKey(aesKey);
            Cipher cipher = Cipher.getInstance(AES_TYPE);
            cipher.init(Cipher.DECRYPT_MODE, key);
            decrypt = cipher.doFinal(Base64.decodeBase64(encryptData));
            return new String(decrypt).trim();
        } catch (Exception e) {
            logger.error("decrypt Exception", e);
        }
        return null;
    }

    private static Key generateKey(String key) {
        return new SecretKeySpec(key.getBytes(), ALGORITHM);
    }

    private static void validate(String aesKey) {
        Assert.notEmpty(aesKey, "AES key is required");
        Assert.isTrue(aesKey.length() == 16, "the length of AES key must be 16");
    }
}
